<template>
    <div class="login-container">
        <!-- canvas -->
        <div id="canvasBox"></div>
        <div class="bottomImage">
            <img width="100%" src="../../assets/images/ground.png" alt="">
        </div>
        <div class="container">
            <!-- 飞行员 -->
            <div class="man">
                <img width="200" src="../../assets/images/login_human.png" alt="">
            </div>
            <div class="loginBox">
                <div class="logo">
                    电商后台管理系统
                    <!-- <img src="./images/logo.png" alt=""> -->
                </div>
                <el-form class="login_from" ref="formRef" :model="userForm" :rules="rules">
                    <el-form-item prop="username">
                        <el-input placeholder="请输入账号" v-model="userForm.username" prefix-icon="el-icon-user"></el-input>
                    </el-form-item>
                    <el-form-item prop="password">
                        <el-input placeholder="请输入密码" type="password" v-model="userForm.password"
                            prefix-icon="el-icon-lock"></el-input>
                    </el-form-item>
                    <el-form-item prop="isAgree">
                        <el-checkbox v-model="userForm.isAgree">
                            <span style="color:#fff;">用户平台使用协议</span>
                        </el-checkbox>
                    </el-form-item>
                    <el-form-item>
                        <el-button @click="login" class="login_btn" type="primary">登录</el-button>
                    </el-form-item>
                    <!-- <el-form-item style="background:pink"  class="el-btn-box">
                        <div style="width:100%;background:red">
                            <el-button  type="cyan">忘记密码?</el-button>
                        </div>
                        <div>
                            
                            <el-button  type="cyan" @click="resetForm">重置</el-button>
                        </div>
                    </el-form-item> -->
                    <div class="el-btn-box">
                        <div>
                            <el-button type="cyan">忘记密码?</el-button>
                        </div>
                        <div>
                            <el-button type="cyan" @click="resetForm">重置</el-button>
                        </div>
                    </div>
                </el-form>

            </div>
        </div>
    </div>
</template>

<script>
// threejs
import * as THREE from "three"
// 轨道控制器
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'
// lodash
import _ from 'lodash'
import axios from "axios"
export default {
    name: 'MyLogin',
    data() {
        return {
            // 账号密码
            userForm: {
                // 用户名
                username: 'admin',
                // 密码
                password: '00000000',
                isAgree: null
            },
            // 验证规则
            rules: {
                // 用户验证
                username: [
                    { required: true, message: '请输入登录名称', trigger: 'blur' },
                    { min: 4, max: 11, message: '长度在 4 到 11 个字符', trigger: 'blur' }
                ],
                // 密码验证
                password: [
                    { required: true, message: '请输入登录密码', trigger: 'blur' },
                    { min: 5, max: 15, message: '长度在 5 到 15 个字符', trigger: 'blur' }
                ],
                isAgree: [{
                    validator: (rule, value, callback) => {
                        // rule校验规则
                        // value 校验的值
                        // callback 函数 - promise resolve reject
                        // callback() callback(new Error(错误信息))
                        value ? callback() : callback(new Error('您必须勾选用户的使用协议'))
                    }
                }]
            },
            // container存放整个div的地方
            container: '',
            scene: '',
            // 宽度
            width: '',
            // // 高度
            height: '',
            // 深度
            depth: 1400,
        }
    },
    created() {
        // 背景图
        this.IMAGE_SKY = new URL("../../assets/images/sky.png", import.meta.url).href
        // 地球
        this.IMAGE_EARTH = new URL("../../assets/images/earth_bg.png", import.meta.url).href
        // 星星
        this.IMAGE_STAR1 = new URL("../../assets/images/starflake1.png", import.meta.url).href
        // 星星
        this.IMAGE_STAR2 = new URL("../../assets/images/starflake2.png", import.meta.url).href
        this.IMAGE_CLOUD = new URL("../../assets/images/cloud.png", import.meta.url).href
        this.zAxisNumber
        this.renderer
        // 点的初始参数
        this.parameters
        // 星星材质
        this.materials = []
        // 星星初始位置
        this.particles_init_position
        // 声明点1在z轴上的移动位置
        this.zprogress
        // 声明点2在z轴上的移动位置
        this.zprogress_second
        // 声明点1的数组
        this.particles_first = []
        // 声明点2的数组
        this.particles_second = []
        // 声明云对象1
        this.cloud_first
        // 声明云对象2
        this.cloud_second
        // 声明星云运动的渲染函数1
        this.renderCloud_first
        // 声明星云运动的渲染函数2
        this.renderCloud_second
    },
    methods: {
        // 登录按钮
        login() {
            // 看验证 表单是否验证成功
            this.$refs.formRef.validate(async isOk => {
                // console.log(isOk);
                if (!isOk) return
                // 添加token 测试接口 mock.js
                const res = await axios.get("/data")
                console.log(res);
                if (res.data.code !== 200) {
                    return this.$message.error("登录失败")
                } else {
                    window.sessionStorage.setItem('token', res.data.token)
                    this.$message.success("登录成功")
                    this.$router.push("/home")
                }
                // 需要token
                // 如果状态码不等于200
                // if(res.code!== 200) {
                //     return this.$message.error("登录失败")
                // }else {
                //     window.sessionStorage.setItem('token',token)
                // }
            })
        },
        // 重置表单
        resetForm() {
            this.$refs.formRef.resetFields()
        },
        // 初始化场景
        initScene() {
            // 创建场景
            this.scene = new THREE.Scene()
            // 添加雾的效果
            this.scene.fog = new THREE.Fog(0x000000, 0, 10000)
        },
        // 添加背景
        initSceneBg() {
            // 纹理
            new THREE.TextureLoader().load(this.IMAGE_SKY, (texture) => {
                // 创建立方体
                this.geometry = new THREE.BoxGeometry(this.width, this.height, this.depth)
                // 创建材质
                this.material = new THREE.MeshBasicMaterial({ map: texture, side: THREE.BackSide })
                // 创建网格
                this.mesh = new THREE.Mesh(this.geometry, this.material)
                // 添加到场景
                this.scene.add(this.mesh)
            })
        },
        // 初始化相机
        initCamera() {
            // 视野夹角
            this.fov = 15
            // 计算相机距离物体的距离
            this.distance = this.width / 2 / Math.tan(Math.PI / 12)
            this.zAxisNumber = Math.floor(this.distance - 1400 / 2)
            // 相机
            this.camera = new THREE.PerspectiveCamera(this.fov, this.width / this.height, 1, 30000)
            // 设置相机所在位置
            this.camera.position.set(0, 0, this.zAxisNumber)
            // 看向原点
            this.camera.lookAt(0, 0, 0)
        },
        // 初始化球体
        initSphereModal() {
            // 创建一个球体 球的半径 水平分段数 垂直分段数
            const geometry = new THREE.SphereGeometry(50, 64, 32)
            // 创建材质
            const material = new THREE.MeshPhongMaterial()
            material.map = new THREE.TextureLoader().load(this.IMAGE_EARTH)
            // 创建网格
            this.sphere = new THREE.Mesh(geometry, material)
            // 球体位置
            this.sphere.position.set(-400, 200, -200)
            this.scene.add(this.sphere)
        },
        // 初始化光源
        initLight() {
            // 环境光
            const ambientLight = new THREE.AmbientLight(0xffffff, 1)
            this.scene.add(ambientLight)
            // 点光源
            const light = new THREE.PointLight(0x0655fd, 5, 0)
            light.position.set(0, 100, -200)
            this.scene.add(light)
        },
        // 渲染器
        initRenderer() {
            // 创建渲染器
            this.renderer = new THREE.WebGLRenderer()
            // 定义渲染器的尺寸
            this.renderer.setSize(this.width, this.height)
            // console.log(this.width);
            // console.log(this.height);
            this.container.appendChild(this.renderer.domElement)
        },
        // 星球自转
        renderSphereRotate() {
            this.sphere.rotateY(0.01)
        },
        // 初始化星星
        initSceneStar(initZposition) {
            const geometry = new THREE.BufferGeometry()
            // 星星位置的坐标
            const vertices = []
            // 创建纹理
            const textureLoader = new THREE.TextureLoader()
            const spritel = textureLoader.load(this.IMAGE_STAR1)
            const sprite2 = textureLoader.load(this.IMAGE_STAR2)
            // 接收星星的数据
            const pointsGeomtry = []
            // 声明点的参数
            this.parameters = [
                [[0.6, 100, 0.75], spritel, 50],
                [[0, 0, 1], sprite2, 20]
            ]
            // 创建多个星星
            for (let i = 0; i < 1500; i++) {
                const x = THREE.MathUtils.randFloatSpread(this.width)
                const y = _.random(0, this.height / 2)
                const z = _.random(-this.depth / 2, this.zAxisNumber)
                vertices.push(x, y, z)
            }
            geometry.setAttribute('position', new THREE.Float32BufferAttribute(vertices, 3))
            // 创建两种不同的材质
            for (let i = 0; i < this.parameters.length; i++) {
                // 颜色
                const color = this.parameters[i][0]
                // 纹理
                const sprite = this.parameters[i][1]
                // 点的大小
                const size = this.parameters[i][2]
                this.materials[i] = new THREE.PointsMaterial({
                    size,
                    map: sprite,
                    blending: THREE.AdditiveBlending,
                    // 背景透明度
                    transparent: true,
                    // 深度测试
                    depthTest: true
                })
                this.materials[i].color.setHSL(color[0], color[1], color[2])
                // 创建物体
                const particles = new THREE.Points(geometry, this.materials[i])
                particles.rotation.x = Math.random() * 0.2 - 0.15
                particles.rotation.y = Math.random() * 0.2 - 0.15
                particles.rotation.z = Math.random() * 0.2 - 0.15
                particles.position.setZ(initZposition)
                pointsGeomtry.push(particles)
                this.scene.add(particles)
            }
            return pointsGeomtry
        },
        // 渲染星星的运动
        renderStarMove() {
            // 星星的颜色交替变化
            const time = Date.now() * 0.00005
            for (let i = 0; i < this.parameters.length; i++) {
                const color = this.parameters[i][0]
                const h = ((360 * (color[0] + time)) % 360) / 360
                this.materials[i].color.setHSL(color[0], color[1], parseFloat(h.toFixed(2)))
            }
            // 运动
            this.zprogress += 2
            this.zprogress_second += 2
            // 点1的运动
            if (this.zprogress >= this.zAxisNumber + this.depth / 2) {
                this.zprogress = this.particles_init_position
            } else {
                this.particles_first.forEach(item => {
                    item.position.setZ(this.zprogress)
                })
            }
            // 点2的运动
            if (this.zprogress_second >= this.zAxisNumber + this.depth / 2) {
                this.zprogress_second = this.particles_init_position
            } else {
                this.particles_first.forEach(item => {
                    item.position.setZ(this.zprogress_second)
                })
            }

        },
        // 渲染星云的效果
        initCloud(width, height) {
            const geometry = new THREE.PlaneGeometry(width, height)
            const cloudTexture = new THREE.TextureLoader().load(this.IMAGE_CLOUD)
            const cloudMater = new THREE.MeshBasicMaterial({
                map: cloudTexture,
                blending: THREE.AdditiveBlending,
                transparent: true,
                depthTest: false
            })
            const cloud = new THREE.Mesh(geometry, cloudMater)
            this.scene.add(cloud)
            return cloud
        },
        // 创建星云运动的函数
        initCloudMove(cloud, route, speed) {
            let cloudProgress = 0
            // 创建三维曲线
            const curve = new THREE.CatmullRomCurve3(route)
            return () => {
                if (cloudProgress <= 1) {
                    cloudProgress += speed
                    // 获取当前位置
                    const point = curve.getPoint(cloudProgress)
                    if (point && point.x) {
                        cloud.position.set(point.x, point.y, point.z)
                    }
                } else {
                    cloudProgress = 0
                }
            }
        },
        // 轨道控制器
        initOrbitControls() {
            const controls = new OrbitControls(this.camera, this.renderer.domElement)
            controls.enabled = true
            controls.update()
        },
        // 动画
        animate() {
            requestAnimationFrame(this.animate)
            this.renderSphereRotate()
            this.renderStarMove()
            this.renderCloud_first()
            this.renderCloud_second()
            this.renderer.render(this.scene, this.camera)
        }
    },
    mounted() {
        this.container = document.querySelector("#canvasBox")
        this.width = this.container.clientWidth
        this.height = this.container.clientHeight
        // 场景
        this.initScene()
        // 纹理背景
        this.initSceneBg()
        // 球体
        this.initSphereModal()
        // 相机
        this.initCamera()
        // 光源
        this.initLight()
        // 定义星星初始位置
        this.particles_init_position = -this.zAxisNumber - this.depth / 2
        this.zprogress = this.particles_init_position
        this.zprogress_second = this.particles_init_position * 2
        this.particles_first = this.initSceneStar(this.particles_init_position)
        this.particles_second = this.initSceneStar(this.zprogress_second)
        this.cloud_first = this.initCloud(400, 200)
        this.cloud_second = this.initCloud(200, 100)
        this.renderCloud_first = this.initCloudMove(this.cloud_first, [
            new THREE.Vector3(-this.width / 10, 0, -this.depth / 2),
            new THREE.Vector3(-this.width / 4, this.height / 8, 0),
            new THREE.Vector3(-this.width / 4, 0, this.zAxisNumber),
        ], 0.0002)
        this.renderCloud_second = this.initCloudMove(this.cloud_second, [
            new THREE.Vector3(this.width / 8, this.height / 8, -this.depth / 2),
            new THREE.Vector3(this.width / 8, this.height / 8, this.zAxisNumber),
        ], 0.0008)
        // 渲染器
        this.initRenderer()
        // 轨道控制器
        this.initOrbitControls()
        // 动画
        this.animate()
    }
}
</script>

<style lang='scss' scoped>
.btn-grounds {
    color: #fff;
}

// ...............
.el-button--login.is-active,
.el-button--login:active {
    background: #20B2AA;
    border-color: #20B2AA;
    color: #FFFFFF;
}

.el-button--login:focus,
.el-button--login:hover {
    background: #1714b9;
    border-color: #1714b9;
    color: #fff;
}

.el-button--login {
    background: #fff;
    border-color: #1714b9;
    color: #000;
}

// ..............
.el-form-item {
    margin-top: 10px;
    margin-bottom: 25px;
}

.el-input {
    color: #fff;
}

.login-container {
    .bottomImage {
        position: absolute;
        bottom: 0;
        left: 0;
    }

    position: relative;
    width: 100vw;
    height: 100vh;

    #canvasBox {
        width: 100%;
        height: 100%;
    }

    //background-color: rgb(240, 241, 242);
    canvas {
        position: absolute !important;
        top: 0 !important;
        left: 0 !important;
    }

    .container {
        position: absolute;
        top: 0;
        left: 50%;
        transform: translateX(-50%);
        width: 800px;
        height: 100%;
        margin: 0 auto;

        .man {
            z-index: 10;
            position: absolute;
            right: 30px;
            top: 130px;
            animation: manMove 2s linear infinite alternate-reverse;
        }

        .loginBox {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            width: 500px;
            height: 400px;
            background-color: rgb(0, 0, 0);
            // background-color: rgb(67, 99, 175);
            opacity: 0.4;
            box-shadow: 0 0 10px #fff;

            .logo {
                z-index: 1;
                position: absolute;
                left: 50%;
                transform: translate(-50%, -50%);
                font-size: 50px;
                white-space: nowrap;
                color: #fff;
                font-weight: bold;
            }
        }
    }

}

// 动画man
@keyframes manMove {
    0% {
        top: 110px;
    }

    100% {
        top: 150px;
    }
}

.login_from {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    width: 100%;
    padding: 0 50px;
    margin-top: 40px;
    box-sizing: border-box;
}

.login_btn {
    width: 100%;
    font-size: 18px;
}

.el-btn-box {
    color: #fff;
    display: flex;
    justify-content: space-between;

    .el-form-item__content {
        width: 100%;
    }

    .el-button {
        border: none;
    }
}
</style>